
macro( nane_add_implementation subsystem subsystem_impl )
    if( "${ARGV2}" STREQUAL "SHARED" )
        set( NANE_${subsystem}_SHARED_IMPL ${NANE_${subsystem}_SHARED_IMPL} ${subsystem_impl} )
    else()
        set( NANE_${subsystem}_IMPL ${NANE_${subsystem}_IMPL} ${subsystem_impl} )
    endif()
endmacro()

macro( nane_add_implementation_targets subsystem )
    set( NANE_OLD_IMPL_MODE ${NANE_OLD_IMPL_MODE} )
    set( NANE_IMPL_MODE STATIC )
    foreach( subsystem_impl ${NANE_${subsystem}_IMPL} )
        add_subdirectory( ${subsystem_impl} )
    endforeach()
    set( NANE_IMPL_MODE SHARED )
    foreach( subsystem_impl ${NANE_${subsystem}_SHARED_IMPL} )
        add_subdirectory( ${subsystem_impl} )
    endforeach()
    set( NANE_IMPL_MODE ${NANE_OLD_IMPL_MODE} )
endmacro()

macro( nane_override_implementations subsystem )
    set( NANE_${subsystem}_IMPL )
    set( NANE_${subsystem}_SHARED_IMPL )
endmacro()

macro( nane_add_module module_name subsystem header version )
    set( NANE_MODULE_INTERFACE ${subsystem} )
    set( NANE_MODULE_NAME ${module_name} )
    set( NANE_MODULE_HEADER ${header} )
    set( NANE_MODULE_VERSION ${version} )
    set( NANE_MODULE_EXPORT )
    remove_definitions( -DNANE_MODULE_SHARED )
    if( "${NANE_IMPL_MODE}" STREQUAL "SHARED" )
        if( WIN32 )
            set( NANE_MODULE_EXPORT "__declspec(dllexport)" )
        else()
            set( NANE_MODULE_EXPORT "extern" )
        endif()
        add_definitions( -DNANE_MODULE_SHARED )
    else()
        set( NANE_MODULES_DECLARATION ${NANE_MODULES_DECLARATION} "    extern bool init_${NANE_MODULE_NAME}();\n" )
        set( NANE_MODULES_IMPLEMENTATION ${NANE_MODULES_IMPLEMENTATION} "        init_${NANE_MODULE_NAME}();\n" )
        set( NANE_MODULES_DECLARATION ${NANE_MODULES_DECLARATION} PARENT_SCOPE )
        set( NANE_MODULES_IMPLEMENTATION ${NANE_MODULES_IMPLEMENTATION} PARENT_SCOPE )
    endif()
    configure_file(${NANE_SOURCE_DIR}/cmake/ModuleMain.template ${CMAKE_CURRENT_BINARY_DIR}/ModuleMain.cpp @ONLY)
    set( ${module_name}_system ${subsystem} )
    set( ${module_name}_src ${CMAKE_CURRENT_BINARY_DIR}/ModuleMain.cpp )
    foreach( sourcefile ${ARGN} )
        set( ${module_name}_src ${${module_name}_src} ${CMAKE_CURRENT_SOURCE_DIR}/${sourcefile} )
    endforeach()
    if( "${NANE_IMPL_MODE}" STREQUAL "SHARED" )
        foreach( config ${thirdparty_configs} )
            include( ${config} )
        endforeach()
        add_library( ${module_name} ${NANE_IMPL_MODE} ${${module_name}_src} )
        set_target_properties(${module_name} PROPERTIES PREFIX "")
        target_link_libraries( ${module_name} ${nane_thirdparty_libs} nane_core )
    else()
        set( NANE_${${module_name}_system}_IMPL_CONFIGS ${NANE_${${module_name}_system}_IMPL_CONFIGS} ${thirdparty_configs} PARENT_SCOPE )
        set( NANE_${module_name}_IMPL_SRC ${NANE_${module_name}_IMPL_SRC} ${${module_name}_src} PARENT_SCOPE )
        set( NANE_${subsystem}_SRC_GROUPS ${NANE_${subsystem}_SRC_GROUPS} ${module_name} PARENT_SCOPE )
    endif()
endmacro()

macro( nane_add_source_file sourcefile )
    get_filename_component(${library_name}_install_dir ${sourcefile} PATH)
    install(FILES ${NANE_SOURCE_DIR}/${sourcefile} DESTINATION include/nane/${${library_name}_install_dir})
endmacro()

macro( nane_add_library library_name )
    set( ${library_name}_src )
    foreach( sourcefile ${ARGN} )
        if( "${sourcefile}" MATCHES ".*[^_]\\.h$" )
            nane_add_source_file( ${sourcefile} )
        endif()
        set( ${library_name}_src ${${library_name}_src} ${NANE_SOURCE_DIR}/${sourcefile})
    endforeach()
    foreach( config ${NANE_${library_name}_IMPL_CONFIGS} )
        include( ${config} )
    endforeach()
    source_group( ${library_name} FILES ${${library_name}_src} )
    foreach( sourcegroup ${NANE_${library_name}_SRC_GROUPS} )
        source_group( ${sourcegroup} FILES ${NANE_${sourcegroup}_IMPL_SRC} )
        set( ${library_name}_src ${${library_name}_src} ${NANE_${sourcegroup}_IMPL_SRC} )
    endforeach()
    add_library( nane_${library_name} ${${library_name}_src} )
    target_link_libraries( nane_${library_name} nane_core ${nane_thirdparty_libs} )
    install(TARGETS nane_${library_name} DESTINATION lib)

    set( NANE_SUBSYSTEMS ${NANE_SUBSYSTEMS} ${library_name} PARENT_SCOPE )
    set( NANE_MODULES_DECLARATION ${NANE_MODULES_DECLARATION} PARENT_SCOPE )
    set( NANE_MODULES_IMPLEMENTATION ${NANE_MODULES_IMPLEMENTATION} PARENT_SCOPE )
    set( NANE_SUBSYSTEM_TARGETS ${NANE_SUBSYSTEM_TARGETS} nane_${library_name} PARENT_SCOPE )
endmacro()

macro( nane_include_thirdparty name )
	if( NOT DEFINED nane_thirdparty_${name}_included )
        set( thirdparty_configs ${thirdparty_configs} ${NANE_SOURCE_DIR}/thirdparty/${nane_thirdparty_${name}_config} )
        set( nane_thirdparty_${name}_included )
    endif()
endmacro()

macro( nane_add_thirdparty name subdir )
    if( DEFINED nane_thirdparty_${name}_config )
        message( WARNING "thirdparty ${name} already included. overwriting" )
    endif()
    foreach( dependency ${ARGN} )
        include( ${dependency}.cmake )
    endforeach()
    add_subdirectory( ${subdir} )
    set( nane_thirdparty_${name}_config ${name}.cmake )
    set( nane_thirdparty_${name}_config ${nane_thirdparty_${name}_config} PARENT_SCOPE ) # push top
endmacro()
